﻿using DTcms.Common;
using System;
using System.Collections.Generic;
using System.Text;

namespace DTcms.SMS.CCP
{
    /// <summary>
    /// 云通讯
    /// https://www.yuntongxun.com
    /// </summary>
    public class CCPSms : ISms
    {
        /// <summary>
        /// ACCOUNT SID  主账号
        /// </summary>
        private readonly string sid;

        /// <summary>
        /// AUTH TOKEN  主账号令牌
        /// </summary>
        private readonly string token;

        /// <summary>
        /// AppID  应用ID
        /// </summary>
        private readonly string AppID;

        /// <summary>
        /// 同一手机单日最大允许发送量
        /// </summary>
        private readonly int sendCount;

        /// <summary>
        /// 同一IP地址，单日最大允许提交请求次数
        /// </summary>
        private readonly int ipCount;

        /// <summary>
        /// 平台单日发送上限
        /// </summary>
        private readonly int safeTotal;
        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="username">sid</param>
        /// <param name="password">token</param>
        /// <param name="appid">appid</param>
        /// <param name="sendCount">同一手机单日最大允许发送量</param>
        /// <param name="ipCount">同一IP地址，单日最大允许提交请求次数</param>
        /// <param name="safeTotal">平台单日发送上限</param>
        public CCPSms(string sid, string token, string appid, int sendCount, int ipCount, int safeTotal)
        {
            this.sid = sid;
            if (!string.IsNullOrEmpty(token))
            {
                this.token = Utils.MD5(DESEncrypt.Decrypt(token));
            }
            else
            {
                this.token = string.Empty;
            }
            this.AppID = appid;
            this.sendCount = sendCount;
            this.ipCount = ipCount;
            this.safeTotal = safeTotal;
        }

        /// <summary>
        /// 手机短信（单条发送）
        /// </summary>
        /// <param name="mobile">手机号码</param>
        /// <param name="content">短信模板编号</param>
        /// <param name="pass">无作用（备用）</param>
        /// <param name="msg">返回提示信息</param>
        /// <param name="paramJsonString">关键词替换  用于替换模板中的关键词，string[] data = { 1, 2 };  格式以,分割传递数据</param>
        /// <returns>bool</returns>
        public bool Send(string mobiles, string templateId, int pass, string paramJsonString, out string msg)
        {
            string[] data = paramJsonString.Split(',');
            if (string.IsNullOrEmpty(sid) || string.IsNullOrEmpty(token) || string.IsNullOrEmpty(AppID))
            {
                msg = "短信配置参数有误，请完善后再提交！";
                return false;
            }
            //验证手机号码
            if (!Utils.IsMobilePhone(mobiles))
            {
                msg = "手机号码格式不正确！";
                return false;
            }
            if (string.IsNullOrEmpty(templateId))
            {
                msg = "短信模板编号不能为空！";
                return false;
            }

            bool status = true;
            BLL.sms_log bll = new BLL.sms_log();
            //查询是否超出平台限制
            int thisSafeTotal = bll.GetCurDayCount();
            if (this.safeTotal > 0 && thisSafeTotal > this.safeTotal)
            {
                msg = "对不起，平台短信发送量已超出最大限制！";
                return false;
            }

            //查询当前IP是否已经超出限制
            string ip = DTRequest.GetIP();
            int thisIpSendCount = bll.GetIPCount(ip);
            if (this.ipCount > 0 && thisIpSendCount > this.ipCount)
            {
                msg = "对不起，你的网络已经超出发送数量限制！";
                return false;
            }

            msg = string.Empty;
            if (status)
            {
                //发送短信
                Model.sms_log model = new Model.sms_log();
                model.mobile = mobiles;
                model.content = templateId;
                model.send_time = DateTime.Now;
                try
                {
                    CCPRestSDK api = new CCPRestSDK();
                    bool isInit = api.init("app.cloopen.com", "8883");
                    api.setAccount(sid, token);
                    api.setAppId(AppID);
                    if (isInit)
                    {
                        Dictionary<string, object> retData = api.SendTemplateSMS(mobiles, templateId, data);
                        msg = getDictionaryData(retData);
                        if (retData["statusCode"].ToString() == "000000")
                        {
                            msg = "发送成功！";
                        }
                        else
                        {
                            msg = retData["statusMsg"].ToString();
                        }
                    }
                    else
                    {
                        msg = "初始化失败";
                        return false;
                    }
                }
                catch (Exception ex)
                {
                    status = false;
                    model.status = 1;
                    model.remark = "提交失败，错误提示：" + ex.Message;
                    msg = model.remark;
                }
                bll.Add(model);
            }

            //返回状态
            if (status)
            {
                msg = "发送成功！";
                return true;
            }
            return false;
        }

        // <summary>
        /// 手机短信（批量发送）
        /// 注意：批量发送只验证平台发送总数限制；
        /// </summary>
        /// <param name="mobiles">手机号码，以英文“,”逗号分隔开</param>
        /// <param name="content">短信模板编号</param>
        /// <param name="pass">无作用（备用）</param>
        /// <param name="msg">返回提示信息</param>
        /// <param name="paramJsonString">关键词替换  用于替换模板中的关键词，string[] data = { 1, 2 };  格式以“,”分割传递数据</param>
        /// <returns>bool</returns>
        public bool MultiSend(string mobiles, string templateId, int pass, string paramJsonString, out string msg)
        {
            string[] data = paramJsonString.Split(',');
            if (string.IsNullOrEmpty(sid) || string.IsNullOrEmpty(token) || string.IsNullOrEmpty(AppID))
            {
                msg = "短信配置参数有误，请完善后再提交！";
                return false;
            }
            if (string.IsNullOrEmpty(templateId))
            {
                msg = "短信模板编号不能为空！";
                return false;
            }
            int sucCount = 0;
            string[] oldMobileArr = mobiles.Split(',');

            BLL.sms_log bll = new BLL.sms_log();
            //查询是否超出平台限制
            int thisSafeTotal = bll.GetCurDayCount();
            if (this.safeTotal > 0 && thisSafeTotal > this.safeTotal)
            {
                msg = "对不起，平台短信发送量已超出最大限制！";
                return false;
            }
            //错误消息
            string errorMsg = string.Empty;

            //200条为一批，求出分多少批  最多两百个
            int batch = oldMobileArr.Length / 200 + 1;
            for (int i = 0; i < batch; i++)
            {
                StringBuilder sb = new StringBuilder();
                int sendCount = 0; //发送数量
                int maxLenght = (i + 1) * 2000; //循环最大的数

                //检测号码，忽略不合格的，重新组合
                for (int j = 0; j < oldMobileArr.Length && j < maxLenght; j++)
                {
                    int arrNum = j + (i * 2000);
                    string mobile = oldMobileArr[arrNum].Trim();
                    if (!Utils.IsMobilePhone(mobile))//验证手机号码
                    {
                        sendCount++;
                        sb.Append(mobile + ",");
                    }
                }

                //发送短信
                if (sb.ToString().Length > 0)
                {
                    try
                    {
                        CCPRestSDK api = new CCPRestSDK();
                        bool isInit = api.init("app.cloopen.com", "8883");
                        api.setAccount(sid, token);
                        api.setAppId(AppID);
                        if (isInit)
                        {
                            Dictionary<string, object> retData = api.SendTemplateSMS(Utils.DelLastComma(sb.ToString()), templateId, data);
                            msg = getDictionaryData(retData);
                            if (retData["statusCode"].ToString() == "000000")
                            {
                                msg = "发送成功！";
                            }
                            else
                            {
                                msg  = retData["statusMsg"].ToString();
                            }
                        }
                        else
                        {
                            msg = "初始化失败";
                            return false;
                        }
                    }
                    catch (Exception ex)
                    {
                        errorMsg = "提交失败，错误提示：" + ex.Message;
                    }  
                }
            }
            //返回状态
            if (sucCount > 0)
            {
                msg = "成功提交" + sucCount + "条，失败" + (oldMobileArr.Length - sucCount) + "条";
                return true;
            }
            msg = errorMsg;
            return false;
        }

        /// <summary>
        /// 查询账户剩余短信数量
        /// </summary>
        public string GetAccountQuantity()
        {
            return "没有提供查询接口";
        }

        private string getDictionaryData(Dictionary<string, object> data)
        {
            string ret = null;
            foreach (KeyValuePair<string, object> item in data)
            {
                if (item.Value != null && item.Value.GetType() == typeof(Dictionary<string, object>))
                {
                    ret += item.Key.ToString() + "={";
                    ret += getDictionaryData((Dictionary<string, object>)item.Value);
                    ret += "};";
                }
                else
                {
                    ret += item.Key.ToString() + "=" + (item.Value == null ? "null" : item.Value.ToString()) + ";";
                }
            }
            return ret;
        }

        /// <summary>
        /// 错误列表
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, string> ErrorDic()
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            dic.Add("111000 ", "未知错误");
            dic.Add("111001-111099 ", "内部错误");
            dic.Add("111100", "【账号】请求URL账号格式不正确");
            dic.Add("111101", "【账号】请求包头Authorization参数为空");
            dic.Add("111102", "【账号】请求包头Authorization参数Base64解码失败");
            dic.Add("111103", "【账号】请求包头Authorization参数解码后格式有误");
            dic.Add("111104", "【账号】请求包头Authorization参数解码后账户ID为空");
            dic.Add("111105", "【账号】请求包头Authorization参数解码后时间戳为空");
            dic.Add("111106", "【账号】请求包头Authorization参数解码后时间戳过期");
            dic.Add("111107", "【账号】请求包头Authorization参数中账户ID跟请求地址中的账户ID不一致");
            dic.Add("111108", "【账号】请求地址Sig参数为空");
            dic.Add("111109", "【账号】请求地址Sig校验失败");
            dic.Add("111110", "【账号】请求地址SoftVersion参数有误");
            dic.Add("111111", "【账号】超过规定的并发数");
            dic.Add("111112", "【账号】同一号码呼叫超过规定的并发数");
            dic.Add("111113", "【账号】请求包头Authorization参数中时间戳格式有误，请参考yyyyMMddHHmmss");
            dic.Add("111114", "【账号】资源使用超过规定的并发数");
            dic.Add("111115", "【账号】IP地址不在白名单中");
            dic.Add("111116", "【账号】接口调用间隔过短");
            dic.Add("111128", "【账号】主账户ID为空");
            dic.Add("111129", "【账号】主账户ID存在非法字符");
            dic.Add("111130", "【账号】主账户ID长度有误");
            dic.Add("111131", "【账号】主账户授权令牌为空");
            dic.Add("111132", "【账号】主账户授权令牌存在非法字符");
            dic.Add("111133", "【账号】主账户授权令牌长度有误");
            dic.Add("111134", "【账号】主账户名称重复");
            dic.Add("111135", "【账号】主账户名称为空");
            dic.Add("111136", "【账号】主账户名称存在非法字符");
            dic.Add("111137", "【账号】主账户名称长度有误");
            dic.Add("111138", "【账号】主账户未激活");
            dic.Add("111139", "【账号】主账户已暂停");
            dic.Add("111140", "【账号】主账户已关闭");
            dic.Add("111141", "【账号】主账户不存在");
            dic.Add("111142", "【账号】主账户余额不足");
            dic.Add("111143", "【账号】主账号授权令牌无效");
            dic.Add("111144", "【账号】子账户ID为空");
            dic.Add("111145", "【账号】子账户ID存在非法字符");
            dic.Add("111146", "【账号】子账户ID长度有误");
            dic.Add("111147", "【账号】子账户授权令牌为空");
            dic.Add("111148", "【账号】子账户授权令牌存在非法字符");
            dic.Add("111149", "【账号】子账户授权令牌长度有误");
            dic.Add("111150", "【账号】子账户名称重复");
            dic.Add("111151", "【账号】子账户名称为空");
            dic.Add("111152", "【账号】子账户名称存在非法字符");
            dic.Add("111153", "【账号】子账户名称长度有误");
            dic.Add("111154", "【账号】子账户未激活");
            dic.Add("111155", "【账号】子账户已暂停");
            dic.Add("111156", "【账号】子账户已关闭");
            dic.Add("111157", "【账号】子账户不存在");
            dic.Add("111158", "【账号】子账户余额不足");
            dic.Add("111159", "【账号】子账号授权令牌无效");
            dic.Add("111160", "【账号】通讯账号为空");
            dic.Add("111161", "【账号】通讯账号存在非法字符");
            dic.Add("111162", "【账号】通讯账号长度有误");
            dic.Add("111163", "【账号】通讯账号密码为空");
            dic.Add("111164", "【账号】通讯账号密码存在非法字符");
            dic.Add("111165", "【账号】通讯账号密码长度有误");
            dic.Add("111166", "【账号】通讯账号已停用");
            dic.Add("111167", "【账号】通讯账号不存在");
            dic.Add("111168", "【账号】通讯账号密码校验无效");
            dic.Add("111169", "【账号】应用ID为空");
            dic.Add("111170", "【账号】应用ID存在非法字符");
            dic.Add("111171", "【账号】应用ID长度有误");
            dic.Add("111172", "【账号】应用名称重复");
            dic.Add("111173", "【账号】应用名称为空");
            dic.Add("111174", "【账号】应用名称存在非法字符");
            dic.Add("111175", "【账号】应用名称长度有误");
            dic.Add("111176", "【账号】应用被删除");
            dic.Add("111177", "【账号】应用被禁用");
            dic.Add("111178", "【账号】应用未发布");
            dic.Add("111179", "【账号】应用在审核中");
            dic.Add("111180", "【账号】应用被暂停");
            dic.Add("111181", "【账号】应用不存在");
            dic.Add("111182", "【账号】应用不属于主账户");
            dic.Add("111183", "【账号】子账户不属于主账户");
            dic.Add("111184", "【账号】子账户不属于应用");
            dic.Add("111185", "【账号】通讯账号不属于主账户");
            dic.Add("111186", "【账号】通讯账号不属于应用");
            dic.Add("111187", "【账号】通讯账号不属于子账户");
            dic.Add("111188", "【账号】主账户绑定的测试号码个数为零");
            dic.Add("111189", "【账号】获取软交换请求deviceNo与已注册的deviceNo不一致");
            dic.Add("111190", "【账号】话单下载日期规则date参数为空");
            dic.Add("111191", "【账号】话单下载日期规则date参数输入格式有误");
            dic.Add("111192", "【账号】未查到符合条件的话单，请确认话单规则已配置");
            dic.Add("111193", "【账号】Demo应用无权创建子账户");
            dic.Add("111194", "【账号】通过子账户查询通讯账号不存在");
            dic.Add("111195", "【账号】获取软交换请求deviceNo参数为空");
            dic.Add("111196", "【账号】子账户查询请求startNo参数存在非法字符");
            dic.Add("111197", "【账号】子账户查询请求offset参数存在非法字符");
            dic.Add("111198", "【账号】子账户查询请求offset参数超过上限");
            dic.Add("111199", "【账号】子账户查询请求offset参数小于壹");
            dic.Add("111200", "【账号】渠道不存在");
            dic.Add("111201", "【账号】应用未勾选TTS功能");
            dic.Add("111202", "【账号】应用TTS功能受限，请联系工作人员");
            dic.Add("111203", "【账号】应用网络播放功能受限，请联系工作人员");
            dic.Add("111204", "【账号】请求参数balance为空");
            dic.Add("111205", "【账号】请求参数batchNo为空");
            dic.Add("111206", "【账号】请求参数balance非数字");
            dic.Add("111207", "【账号】虚拟账户充值金额超限");
            dic.Add("111208", "【账号】渠道回调地址为空");
            dic.Add("111209", "【账号】虚拟账户回调验证失败");
            dic.Add("111210", "【账号】主账户不属于渠道");
            dic.Add("111211", "【账号】未配置话单规则");
            dic.Add("111212", "【账号】应用未上线");
            dic.Add("111213", "【账号】话单未生成");
            dic.Add("111214", "【账号】应用状态申请option为空");
            dic.Add("111215", "【账号】应用状态申请industry为空");
            dic.Add("111216", "【账号】应用已上线");
            dic.Add("111217", "【账号】应用不是暂停状态");
            dic.Add("111218", "【账号】根据callSid查询话单callSid为空");
            dic.Add("111219", "【账号】子帐号已启用");
            dic.Add("111220", "【账号】修改应用isIvr取值只能为0和1");
            dic.Add("111221", "【账号】修改应用isAgent取值只能为0和1");
            dic.Add("111222", "【账号】修改应用isTTS取值只能为0和1");
            dic.Add("111223", "【账号】应用状态申请option取值范围为1至3");
            dic.Add("111224", "【账号】修改应用industry不是数字");
            dic.Add("111225", "【账号】软交换不存在");
            dic.Add("111226", "【账号】应用已删除或已禁用");
            dic.Add("111227", "【账号】获取临时密码version格式不正确");
            dic.Add("111229", "【账号】应用和创建时间不能同时为空");
            dic.Add("111230", "【账号】公司ID不存在");
            dic.Add("111252", "【帐号】请求中recordFileType非法");
            dic.Add("111253", "【帐号】请求中recordFileType非法");
            dic.Add("111254", "【帐号】修改应用isRecordAuth取值只能为0和1");
            dic.Add("111255", "【账号】请求中email不能为空");
            dic.Add("111234 ", "查询订单超过限制次数");
            dic.Add("113302 ", "【短信】您正在使用云通讯测试模板且短信接收者不是注册的测试号码");
            dic.Add("160050", " 短信发送失败");
            dic.Add("160031", "【短信】参数解析失败");
            dic.Add("160032", "【短信】短信模板无效");
            dic.Add("160033", "【短信】短信存在黑词");
            dic.Add("160034", "【短信】号码黑名单");
            dic.Add("160035", "【短信】短信下发内容为空");
            dic.Add("160036", "【短信】短信模板类型未知");
            dic.Add("160037", "【短信】短信内容长度限制");
            dic.Add("160038", "【短信】短信验证码发送过频繁");
            dic.Add("160039", "【短信】发送数量超出同模板同号天发送次数上限");
            dic.Add("160040", "【短信】验证码超出同模板同号码天发送上限");
            dic.Add("160041", "【短信】通知超出同模板同号码天发送上限");
            dic.Add("160042", "【短信】号码格式有误");
            dic.Add("160043", "【短信】应用与模板id不匹配");
            dic.Add("160044", "【短信】发送号码为空");
            dic.Add("160045", "【短信】群发号码重复");
            dic.Add("160046", "【短信】营销短信发送内容审核未通过");
            dic.Add("160047", "【短信】询状态报告包体解析失败");
            dic.Add("160048", "【短信】号码数超200限制");
            dic.Add("160049", "【短信】短信内容含敏感词");
            dic.Add("160051", "【短信】营销退订号码");
            dic.Add("160052", "【短信】模板变量格式有误");
            dic.Add("160053", "【短信】IP鉴权失败");
            dic.Add("160054", "【短信】请求重复");
            dic.Add("160055", "【短信】请求reqId超长");
            dic.Add("160056", "【短信】同号码请求内容重复");
            dic.Add("160057", "【短信】短信模板ID要求为数字");
            dic.Add("160058", "【短信】账户无国际短信权限");
            dic.Add("160059", "【短信】国际短信暂不支持群发");
            dic.Add("160060", "【短信】国际短信账户无营销短信权限");
            dic.Add("160061", "【短信】暂不支持的国家码号");
            dic.Add("160062", "【短信】未开通此国家码号");
            dic.Add("160063", "【短信】短信发送失败");
            dic.Add("160064", "【短信】短信发送失败");
            dic.Add("160065", "【短信】子扩展不符合要求");
            return dic;
        }
    }
}
